package cn.iocoder.yudao.module.game.controller.app;

import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.module.game.controller.admin.gameLog.vo.GameLogSaveReqVO;
import cn.iocoder.yudao.module.game.controller.admin.gameToken.vo.GameTokenSaveReqVO;
import cn.iocoder.yudao.module.game.dal.dataobject.gameToken.GameTokenDO;
import cn.iocoder.yudao.module.game.service.gameLog.GameLogService;
import cn.iocoder.yudao.module.game.service.gameToken.GameTokenService;
import cn.iocoder.yudao.module.game.service.otherGame.JDBService;
import cn.iocoder.yudao.module.game.service.otherGame.TADAService;
import cn.iocoder.yudao.module.game.utils.AESEncrypt;
import cn.iocoder.yudao.module.member.controller.admin.user.vo.MemberUserUpdateReqVO;
import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO;
import cn.iocoder.yudao.module.member.enums.MemberExperienceBizTypeEnum;
import cn.iocoder.yudao.module.member.service.level.MemberLevelService;
import cn.iocoder.yudao.module.member.service.user.MemberUserService;
import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO;
import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletTransactionDO;
import cn.iocoder.yudao.module.pay.enums.wallet.PayWalletBizTypeEnum;
import cn.iocoder.yudao.module.pay.service.wallet.PayWalletService;
import cn.iocoder.yudao.module.pay.service.wallet.PayWalletTransactionService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.common.enums.UserTypeEnum.MEMBER;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.error;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;

@Tag(name = "用户 APP - 用户收件地址")
@RestController
@RequestMapping("/game/tada")
@Validated
public class AppTADAController {


    @Resource
    private TADAService tadaService;

    @Resource
    private GameLogService gameLogService;

    @Resource
    private MemberUserService memberUserService;
    @Resource
    private PayWalletService payWalletService;
    @Resource
    private PayWalletTransactionService payWalletTransactionService;
    @Resource
    private MemberLevelService memberlevelService;

    @PostMapping("/getGame")
    @Operation(summary = "登录")
    public CommonResult<Map<String, String>> getGame(@RequestBody Map<String, Object> params) throws Exception {
        params.put("token", tadaService.getToken(params.get("userId").toString()));
        return success(tadaService.login(params));
    }

    @PostMapping("/auth")
    @Operation(summary = "创建用户收件地址")
    public Map<String, Object> auth(@RequestBody Map<String, Object> params) throws Exception {
        GameTokenDO gameTokenDO = tadaService.checkToken(params.get("token").toString());
        if (gameTokenDO == null) {
            createLog(null, params);
            return errorRsp(4L, "token has expired");
        }

        return successRsp(gameTokenDO.getMemberId(), "");
    }

    @PostMapping("/bet")
    @Operation(summary = "创建用户收件地址")
    public Map<String, Object> bet(@RequestBody Map<String, Object> params) throws Exception {
        GameTokenDO gameTokenDO = tadaService.checkToken(params.get("token").toString());
        if (gameTokenDO == null) {
            createLog(null, params);
            return errorRsp(4L, "token has expired");
        }

        createLog(gameTokenDO.getMemberId(), params);
        changeBalance(gameTokenDO.getMemberId(), params);

        return successRsp(gameTokenDO.getMemberId(), "");
    }

    @PostMapping("/cancelBet")
    @Operation(summary = "创建用户收件地址")
    public Map<String, Object> cancelBet(@RequestBody Map<String, Object> params) throws Exception {
        GameTokenDO gameTokenDO = tadaService.checkToken(params.get("token").toString());
        if (gameTokenDO == null) {
            createLog(null, params);
            return errorRsp(4L, "token has expired");
        }

        createLog(gameTokenDO.getMemberId(), params);
        changeBalance(gameTokenDO.getMemberId(), params);

        return successRsp(gameTokenDO.getMemberId(), "");
    }

    @PostMapping("/sessionBet")
    @Operation(summary = "创建用户收件地址")
    public Map<String, Object> sessionBet(@RequestBody Map<String, Object> params) throws Exception {
        GameTokenDO gameTokenDO = tadaService.checkToken(params.get("token").toString());
        if (gameTokenDO == null) {
            createLog(null, params);
            return errorRsp(4L, "token has expired");
        }

        createLog(gameTokenDO.getMemberId(), params);
        changeBalance(gameTokenDO.getMemberId(), params);

        return successRsp(gameTokenDO.getMemberId(), "");
    }

    @PostMapping("/cancelSessionBet")
    @Operation(summary = "创建用户收件地址")
    public Map<String, Object> cancelSessionBet(@RequestBody Map<String, Object> params) throws Exception {
        GameTokenDO gameTokenDO = tadaService.checkToken(params.get("token").toString());
        if (gameTokenDO == null) {
            createLog(null, params);
            return errorRsp(4L, "token has expired");
        }

        createLog(gameTokenDO.getMemberId(), params);
        changeBalance(gameTokenDO.getMemberId(), params);

        return successRsp(gameTokenDO.getMemberId(), "");
    }

    private void changeBalance(Long memberId, Map<String, Object> params) {
        Map<String, Object> bonus = new HashMap<>();
        bonus.put("5", 50);
        bonus.put("10", 50);
        bonus.put("15", 50);
        bonus.put("20", 50);
        bonus.put("25", 50);
        bonus.put("30", 50);
        bonus.put("40", 100);
        bonus.put("50", 100);
        bonus.put("60", 100);
        bonus.put("70", 100);
        bonus.put("80", 100);
        bonus.put("90", 100);
        bonus.put("100", 100);
        bonus.put("150", 500);
        bonus.put("200", 500);
        bonus.put("250", 500);
        bonus.put("300", 500);
        bonus.put("350", 500);
        bonus.put("400", 500);
        bonus.put("450", 500);
        bonus.put("500", 500);
        bonus.put("600", 1000);
        bonus.put("700", 1000);
        bonus.put("800", 1000);
        bonus.put("900", 1000);
        bonus.put("1000", 1000);
        bonus.put("1500", 5000);
        bonus.put("2000", 5000);
        bonus.put("2500", 5000);
        bonus.put("3000", 5000);
        bonus.put("4000", 10000);
        bonus.put("5000", 10000);
        bonus.put("6000", 10000);
        bonus.put("7000", 10000);
        bonus.put("8000", 10000);
        bonus.put("9000", 10000);
        bonus.put("10000", 10000);

        PayWalletDO payWalletDO = payWalletService.getOrCreateWallet(memberId, MEMBER.getValue());
        payWalletService.addWalletBalance(payWalletDO.getId(),
                params.get("reqId").toString(),
                PayWalletBizTypeEnum.WIN,
                (long)(Double.valueOf(params.get("winloseAmount").toString()) * 100000));
        payWalletService.reduceWalletBalance(payWalletDO.getId(),
                params.get("reqId").toString(),
                PayWalletBizTypeEnum.BET,
                (long)(Double.valueOf(params.get("betAmount").toString()) * 100000));

        MemberUserDO memberUserDO = memberUserService.getUser(memberId);

        memberlevelService.addExperience(memberId,
                (long)(Double.parseDouble(params.get("betAmount").toString())),
                MemberExperienceBizTypeEnum.ORDER_GIVE,
                params.get("reqId").toString());

        List<PayWalletTransactionDO> payWalletTransactionDOS =  payWalletTransactionService.list(memberUserDO.getCode(), PayWalletBizTypeEnum.RECHARGE.getType());
        String sumP =  payWalletTransactionService.betSum(memberUserDO.getCode(), PayWalletBizTypeEnum.BET.getType(), 0).get("sum_p").toString();

        MemberUserDO fReferrerUser = memberUserService.getUserByReferrer(memberUserDO.getReferrer());
        if (fReferrerUser != null) {
            if (payWalletTransactionDOS.size() > 0 && (payWalletTransactionDOS.get(0).getPrice() / 100000) >= 20 && Long.valueOf(sumP) >= 50 && memberUserDO.getReferrerStatus().equals(0)) {
                if (bonus.get(String.valueOf(fReferrerUser.getQualifiedNum() + 1)) != null) {
                    payWalletService.addWalletBalance(payWalletDO.getId(),
                            params.get("reqId").toString(),
                            PayWalletBizTypeEnum.GENERALIZATION_COMMISSION,
                            (long)(Double.parseDouble(bonus.get(String.valueOf(fReferrerUser.getQualifiedNum() + 1)).toString()) * 100000));
                }

                MemberUserUpdateReqVO memberUserUpdateReqVO = new MemberUserUpdateReqVO();
                memberUserUpdateReqVO.setReferrerStatus(1);
                memberUserUpdateReqVO.setQualifiedNum(fReferrerUser.getQualifiedNum() + 1);
                memberUserUpdateReqVO.setId(fReferrerUser.getId());
                memberUserService.updateUser(memberUserUpdateReqVO);
            }

            PayWalletDO fReferrerPayWalletDO = payWalletService.getOrCreateWallet(fReferrerUser.getId(), UserTypeEnum.MEMBER.getValue());
            payWalletService.addWalletBalance(fReferrerPayWalletDO.getId(),
                    params.get("reqId").toString(),
                    PayWalletBizTypeEnum.BET_COMMISSION,
                    (long)(Double.valueOf(params.get("betAmount").toString()) * 100000 * 0.03 / 100));

            MemberUserDO sReferrerUser = memberUserService.getUserByReferrer(fReferrerUser.getReferrer());
            if (sReferrerUser != null) {
                PayWalletDO sReferrerPayWalletDO = payWalletService.getOrCreateWallet(sReferrerUser.getId(), UserTypeEnum.MEMBER.getValue());
                payWalletService.addWalletBalance(sReferrerPayWalletDO.getId(),
                        params.get("reqId").toString(),
                        PayWalletBizTypeEnum.BET_COMMISSION,
                        (long)(Double.valueOf(params.get("betAmount").toString()) * 100000 * 0.01 / 100));

            }
        }
    }

    private void createLog(Long memberId, Map<String, Object> params) {

        String result = params.entrySet().stream()
                .map(entry -> entry.getKey() + "=" + entry.getValue())
                .collect(Collectors.joining(", "));

        GameLogSaveReqVO createReqVO = new GameLogSaveReqVO();
        createReqVO.setMemberId(memberId);
        createReqVO.setGameId(Long.valueOf(params.get("game").toString()));
        createReqVO.setPreChangeCoin(new BigDecimal(params.get("betAmount").toString()));
        createReqVO.setOpeCoin(new BigDecimal(params.get("winloseAmount").toString()));
        createReqVO.setRemark(result);
        gameLogService.createLog(createReqVO);
    }

    private Map<String, Object> successRsp(Long userId, String msg) {
        Map<String, Object> res = new HashMap<>();
        res.put("errorCode", 0);
        res.put("message", msg);
        MemberUserDO memberUserDO = memberUserService.getUser(userId);
        res.put("username", memberUserDO.getMobile());
        res.put("currency", "BRL");

        PayWalletDO payWalletDO = payWalletService.getOrCreateWallet(userId, MEMBER.getValue());
        res.put("balance", new BigDecimal(payWalletDO.getBalance()).divide(new BigDecimal(100000), 2, RoundingMode.HALF_UP));
        return res;
    }

    private Map<String, Object> errorRsp(Long code, String msg) {
        Map<String, Object> res = new HashMap<>();
        res.put("errorCode", code);
        res.put("message", msg);
        return res;
    }

}
